package com.sc.thread.bingfabiancheng;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * Created by Shen Chao on 2018-06-12-012.
 * <p>
 * 字面意思：回环栅栏
 * 通过它可以实现让一组线程等待至某个状态之后再全部同时执行。
 * 叫做回环是因为当所有等待线程都被释放以后，CyclicBarrier可以被重用。
 * 我们暂且把这个状态就叫做barrier，当调用await()方法之后，线程就处于barrier了。
 * <p>
 * 假若有若干个线程都要进行写数据操作，并且只有所有线程都完成写数据操作之后，
 * 这些线程才能继续做后面的事情，此时就可以利用CyclicBarrier了：
 *
 * //如果说想在所有线程写入操作完之后，进行额外的其他操作可以为CyclicBarrier提供Runnable参数：
 * public CyclicBarrier(int parties, Runnable barrierAction) {...}
 */
public class CyclicBarrierTest {
    public static void main(String[] args) {
        int N = 4;
//        CyclicBarrier cyclicBarrier = new CyclicBarrier(N);
        //如果说想在所有线程写入操作完之后，进行额外的其他操作可以为CyclicBarrier提供Runnable参数：
//        CyclicBarrier cyclicBarrier = new CyclicBarrier(N, new Runnable() {
//            @Override
//            public void run() {
//                System.out.println("当前线程：" + Thread.currentThread().getName());
//            }
//        });
        CyclicBarrier cyclicBarrier = new CyclicBarrier(N, () ->
                System.out.println("当前线程：" + Thread.currentThread().getName())
        );

        for (int i = 0; i < N; i++) {
            new Writer(cyclicBarrier).start();
        }
    }

    static class Writer extends Thread {
        private CyclicBarrier cyclicBarrier;

        private Writer(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            try {
                System.out.println("线程：" + Thread.currentThread().getName() + "正在写数据");
                //模拟写数据
                Thread.sleep(3000);
                System.out.println("线程：" + Thread.currentThread().getName() + "写数据完毕，等待其他线程");
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println("所有线程执行完毕，继续执行");
        }
    }
}
